package myJs.myPkg.highcharts

import myJs.Implicits.JDJAn

import java.lang.{Boolean => JBoolean, Double => JDouble, Integer => JInt}
import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.{Promise, native, |}
import slinky.readwrite.{ObjectOrWritten, Writer}

import scala.concurrent.Future
import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.annotation.JSImport

case class Chart(
                  `type`: String,
                  marginTop: js.UndefOr[Int] = js.undefined,
                  marginBottom: js.UndefOr[Int] = js.undefined,
                  plotBorderWidth: js.UndefOr[Int] = js.undefined,
                  height: js.UndefOr[Int] = js.undefined,
                  marginRight: js.UndefOr[Int] = js.undefined,
                  width: js.UndefOr[Int] = js.undefined,
                )

sealed trait Series

case class BoxData(
                    low: js.UndefOr[Double] = js.undefined,
                    q1: js.UndefOr[Double] = js.undefined,
                    median: js.UndefOr[Double] = js.undefined,
                    q3: js.UndefOr[Double] = js.undefined,
                    high: js.UndefOr[Double] = js.undefined,
                    custom: js.UndefOr[js.Dictionary[String]] = js.undefined,
                  )

case class Boxplot(
                    name: js.UndefOr[String] = js.undefined,
                    data: List[BoxData] | List[Double],
                    tooltip: js.UndefOr[Tooltip] = js.undefined,
                    custom: js.UndefOr[js.Array[String]] = js.undefined,
                  ) extends Series

case class DataLabels(
                       enabled: js.UndefOr[Boolean] = js.undefined,
                       tooltip: js.UndefOr[Tooltip] = js.undefined,
                       custom: js.UndefOr[js.Array[String]] = js.undefined,
                       color: js.UndefOr[String] = js.undefined,
                     )

@js.native
trait HeatmapDataT extends js.Object {

  val value: Int = js.native

  val x: Int = js.native

  val y: Int = js.native

  val custom: CustomDataT = js.native

  val graphic: GraphicT = js.native

}

@js.native
trait CustomDataT extends js.Object {

  val updateTime: String = js.native

  val sampleId: String = js.native

}

case class CustomData(
                       updateTime: js.UndefOr[String] = js.undefined,
                       sampleId: js.UndefOr[String] = js.undefined,
                     )

case class HeatmapData(
                        x: js.UndefOr[Int] = js.undefined,
                        y: js.UndefOr[Int] = js.undefined,
                        value: js.UndefOr[Int] = js.undefined,
                        name: js.UndefOr[String] = js.undefined,
                        custom: js.UndefOr[CustomData] = js.undefined,
                        className: js.UndefOr[String] = js.undefined,
                        color: js.UndefOr[String] = js.undefined,
                      )

case class Heatmap(
                    name: js.UndefOr[String] = js.undefined,
                    data: List[HeatmapData],
                    tooltip: js.UndefOr[Tooltip] = js.undefined,
                    custom: js.UndefOr[js.Array[String]] = js.undefined,
                    dataLabels: js.UndefOr[DataLabels] = js.undefined,
                    borderWidth: js.UndefOr[Int] = js.undefined,
                    turboThreshold: js.UndefOr[Int] = js.undefined,
                    borderColor: js.UndefOr[String] = js.undefined,
                    enableMouseTracking: js.UndefOr[Boolean] = js.undefined,
                  ) extends Series

case class Marker(
                   fillColor: js.UndefOr[String] = js.undefined,
                   lineWidth: js.UndefOr[Int] = js.undefined,
                   lineColor: js.UndefOr[String] = js.undefined,
                 )

case class Scatter(
                    name: js.UndefOr[String] = js.undefined,
                    color: js.UndefOr[String] = js.undefined,
                    marker: js.UndefOr[Marker] = js.undefined,
                    tooltip: js.UndefOr[Tooltip] = js.undefined,
                  ) extends Series

case class Labels(
                   style: js.UndefOr[HCStyle] = js.undefined,
                   step: js.UndefOr[Int] = js.undefined
                 )

case class XAxis(
                  categories: js.UndefOr[List[String]] = js.undefined,
                  title: js.UndefOr[Title] = js.undefined,
                  labels: js.UndefOr[Labels] = js.undefined,
                  lineWidth: js.UndefOr[Int] = js.undefined,
                  opposite: js.UndefOr[Boolean] = js.undefined,
                )

case class HCStyle(
                    color: js.UndefOr[String] = js.undefined,
                    fontSize: js.UndefOr[String] = js.undefined,
                    fontFamily: js.UndefOr[String] = js.undefined,
                    fontWeight: js.UndefOr[String] = js.undefined,
                  )

case class Label(
                  text: js.UndefOr[String] = js.undefined,
                  align: js.UndefOr[String] = js.undefined,
                  style: js.UndefOr[HCStyle] = js.undefined,
                )

case class PlotLine(
                     value: js.UndefOr[Int] = js.undefined,
                     color: js.UndefOr[String] = js.undefined,
                     width: js.UndefOr[Int] = js.undefined,
                     label: js.UndefOr[Label] = js.undefined,
                   )

case class YAxis(
                  categories: js.UndefOr[List[String]] = js.undefined,
                  title: js.UndefOr[Title] = js.undefined,
                  plotLines: js.UndefOr[List[PlotLine]] = js.undefined,
                  labels: js.UndefOr[Labels] = js.undefined,
                  lineWidth: js.UndefOr[Int] = js.undefined,
                  reversed: js.UndefOr[Boolean] = js.undefined,
                )

case class Title(
                  text: js.UndefOr[String] = js.undefined,
                )

case class Legend(
                   enabled: js.UndefOr[Boolean] = js.undefined,
                 )

@js.native
trait FormatterData extends js.Object {

  val point: HeatmapDataT = js.native

}

case class Tooltip(
                    pointFormat: js.UndefOr[String] = js.undefined,
                    headerFormat: js.UndefOr[String] = js.undefined,
                    formatter: js.UndefOr[js.ThisFunction0[FormatterData, js.Any]] = js.undefined,
                  )

case class Credits(
                    enabled: js.UndefOr[Boolean] = js.undefined,
                  )

case class BoxplotOption(
                          fillColor: js.UndefOr[String] = js.undefined,
                          lineWidth: js.UndefOr[Int] = js.undefined,
                          medianColor: js.UndefOr[String] = js.undefined,
                          medianWidth: js.UndefOr[Int] = js.undefined,
                          stemColor: js.UndefOr[String] = js.undefined,
                          stemDashStyle: js.UndefOr[String] = js.undefined,
                          stemWidth: js.UndefOr[Int] = js.undefined,
                          whiskerColor: js.UndefOr[String] = js.undefined,
                          whiskerLength: js.UndefOr[String] = js.undefined,
                          whiskerWidth: js.UndefOr[Int] = js.undefined,
                        )

case class ColorAxis(
                      min: js.UndefOr[Int] = js.undefined,
                      minColor: js.UndefOr[String] = js.undefined,
                      maxColor: js.UndefOr[String] = js.undefined,
                    )

@js.native
trait GraphicT extends js.Object {


}

@js.native
trait Event extends js.Object {

  val point: HeatmapDataT = js.native

  val graphic: GraphicT = js.native

}

case class Events(
                   click: js.UndefOr[Event => Unit] = js.undefined,
                   mouseOver: js.UndefOr[js.ThisFunction1[HeatmapDataT, Event, Unit]] = js.undefined
                 )

case class Point(
                  events: js.UndefOr[Events] = js.undefined
                )

case class SeriesOption(
                         point: js.UndefOr[Point] = js.undefined,
                         cursor: js.UndefOr[String] = js.undefined
                       )

case class PlotOptions(
                        boxplot: js.UndefOr[BoxplotOption] = js.undefined,
                        series: js.UndefOr[SeriesOption] = js.undefined,
                      )

case class HighchartsOptions(chart: js.UndefOr[Chart] = js.undefined,
                             series: List[Series], xAxis: XAxis,
                             title: js.UndefOr[Title] = js.undefined,
                             credits: js.UndefOr[Credits] = js.undefined,
                             labels: js.UndefOr[Labels] = js.undefined,
                             plotOptions: js.UndefOr[PlotOptions] = js.undefined,
                             legend: Legend,
                             yAxis: YAxis,
                             tooltip: js.UndefOr[Tooltip] = js.undefined,
                             colorAxis: js.UndefOr[ColorAxis] = js.undefined,
                            )

@js.native
trait HighchartsOptionsT extends js.Object {

  val colors: js.Array[String] = js.native

}

@js.native
@JSImport("highcharts", JSImport.Default)
object Highcharts extends js.Object {

  def chart(container: String,
            options: ObjectOrWritten[HighchartsOptions]
           ): js.Any = js.native

  def getOptions(): HighchartsOptionsT = js.native

}

@js.native
@JSImport("highcharts/modules/heatmap", JSImport.Default)
object HighchartsHeatmap extends js.Object {

  def apply(module: js.Object): js.Any = js.native

}

@js.native
@JSImport("highcharts/highcharts-more", JSImport.Default)
object HighchartsMore extends js.Object {

  def apply(module: js.Object): js.Any = js.native

}
